import json, time
from urllib.parse import unquote
from hashlib import md5

from django.conf import settings
from django_redis import get_redis_connection

from luckin.common import valid_request_param, get_timer
from luckin.models import GoodsOrder, Goods
from luckin.libs.alipay.pay import alipay


class GoodsOrderService:
    _ShopCartKey = "shopCart_%s"
    _ShopCartField = "goods_%s"

    # 获取订单
    def get(self, request):
        # _q : {"page":%s,"state":%s}   1:已支付 2:未支付
        if not valid_request_param(request):
            return False, "参数错误"

        _q = request.query_params.get("_q")
        if not _q:
            return False, "参数错误"
        _q = unquote(_q)
        _s = request.query_params.get("_s")

        param_dict = json.loads(_q)
        page = param_dict.get("page")
        pay_state = param_dict.get("state")

        # 验证传来的数据是否合法
        if not page or not isinstance(page, int):
            return False, "参数错误"
        if not pay_state or pay_state not in [1, 2]:
            return False, "参数错误"

        # 获取当前用户对象
        user = request.user

        # 获取当前用户的订单,一次返回20条数据，根据时间倒叙排序
        page = 1 if page <= 0 else page
        limit = page * 20
        query_set = GoodsOrder.objects.filter(user=user, pay_state=pay_state, is_delete=2).order_by("-create_time")[
                    limit - 20:limit]
        # 判断获取的是已支付订单，还是未支付订单
        # 如果是未支付的订单直接查询,剔除超过规定时间的未支付订单
        query_list = list()
        if pay_state == 1:
            for query_obj in query_set:
                create_time = query_obj.create_time
                timer = get_timer(create_time)
                if timer.seconds < settings.ORDER_NO_PAY_EXPIRATION_TIME:
                    query_list.append(query_obj)
        else:
            query_list.extend(query_set)
        return True, query_list

    # 创建订单
    def post(self, request):
        # 创建一个订单
        # _q : '{"goods_id_list":[1,2,3,4],"price":%s}'
        if not valid_request_param(request):
            return False, "参数错误"
        # 首先订单中的商品，必须是从购物车中得来的
        # 那么请求的数据可以为商品的id，这样我们可以从该用户的购物车中去拿到该商品的信息
        # 在购物车中取数据的时候，同时需要校验商品的id是否存在，不存在直接失败，
        # 都存在的话，就需要将购物车中的相应数据删除掉。
        # 然后在mysql数据中生成订单数据

        _q = request.data.get("_q")
        _s = request.data.get("_s")

        param_dict = json.loads(_q)
        goods_id_list = param_dict.get("goods_id_list")

        # 对参数goods_id_list进行校验
        if not goods_id_list or not isinstance(goods_id_list, list):
            return False, "参数非法"

        # 将购物车中的数据保存在这里
        shop_cart_dict = dict()
        # 拿到redis的链接对象
        redis_conn = get_redis_connection()
        user_id = request.user.id
        redis_h_key = self._ShopCartKey % user_id
        for goods_id in goods_id_list:
            redis_h_field = self._ShopCartField % goods_id
            ok = redis_conn.hexists(redis_h_key, redis_h_field)
            if not ok:
                return False, "参数非法"

        # 能到这里，说明商品都存在购物车中,将购物车中数据取出来
        for goods_id in goods_id_list:
            redis_h_field = self._ShopCartField % goods_id
            redis_result = redis_conn.hget(redis_h_key, redis_h_field)  # redis_result为bytes类型
            redis_result = str(redis_result, encoding="utf-8")  # redis_result为json格式的字符串
            shop_cart_dict[goods_id] = json.loads(redis_result)
            # 删除购物车中的数据
            redis_conn.hdel(redis_h_key, redis_h_field)

        # 校验购物车中的商品，是否还在售卖
        # 比如小明添加了一件限时售卖的商品，但他过了很久才去买，这时商品已经下架，所以不能购买到
        goods_name_list = list()
        for goods_id in goods_id_list:
            goods_obj = Goods.objects.filter(pk=goods_id).first()
            if not goods_obj:
                return False, "商品早已不存在，"
            goods_name = goods_obj.name
            shop_cart_dict[goods_id]["goods_name"] = goods_name
            goods_name_list.append(goods_name)

        # 计算订单商品的总价格
        price = 0
        for key, value in shop_cart_dict.items():
            goods_price = value.get("price")
            goods_count = value.get("goods_count")
            price += goods_price * goods_count

        # 与请求参数中的价格进行校验
        if price != param_dict.get("price"):
            return False, "参数非法"

        # 创建订单记录
        # goods_info字段数据
        shop_cart_json = json.dumps(shop_cart_dict, ensure_ascii=False)
        # order_name字段数据,根据当前时间戳 + 该用户的id生成md5的加密串(确保唯一性)
        order_name = md5(bytes(str(time.time()) + str(user_id), encoding="utf-8")).hexdigest()
        # 生成订单数据
        GoodsOrder.objects.create(user_id=user_id, order_name=order_name, goods_info=shop_cart_json, price=price)

        # 生成支付宝支持的链接参数,返回给前台
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_name,
            total_amount=price,
            subject=goods_name_list[0] if len(goods_name_list) == 1 else "|".join(goods_name_list),
            return_url="http://www.baidu.com"
        )
        return True, "https://openapi.alipaydev.com/gateway.do?" + order_string

    # 删除订单，可以将订单的添加标识删除的字段
    def delete(self, request):
        # _q: '{"order_names":["%s","%s"]}'
        if not valid_request_param(request):
            return False, "参数错误"

        _q = request.data.get("_q")
        _s = request.data.get("_s")

        param_dict = json.loads(_q)
        order_name_list = param_dict.get("order_names")
        # order_name_list必须为List类型
        if not order_name_list or not isinstance(order_name_list, list):
            return False, "参数非法"

        # List中的元素必须是字符串
        for order_name in order_name_list:
            if not isinstance(order_name, str):
                return False, "参数非法"

        # 进行删除操作
        for order_name in order_name_list:
            GoodsOrder.objects.filter(order_name=order_name).updata(is_delete=1)

        return True, "success"
